<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>7.使用噪声绘制纹理-Simplex Noise</title>
    <style>
        canvas{
            border:1px solid #aaa;
            margin: 0 auto;
            display: block;
        }
    </style>
</head>
<body>
    <canvas width="554" height="554"></canvas>
    <script src="/common/lib/gl-renderer.js"></script>

    <script type="module">
        import { loadImage, toPolar, fromPolar } from "/common/lib/utils.js";
        
        /**
         * gl-renderer五步法
         * 1.创建renderer对象
         * 2.创建并启用webgl程序
         * 3.设置uniform变量
         * 4.将定点数据送入缓冲区
         * 5.渲染
         * 
        */
        // 1.
        let canvas = document.querySelector("canvas");
        const renderer = new GlRenderer(canvas);

        // 2.
        const vertex = `
            attribute vec2 a_vertexPosition;
            attribute vec2 uv;
            varying vec2 vUv;

            void main(){
                gl_PointSize = 1.0;
                vUv = uv;
                gl_Position = vec4(a_vertexPosition, 1.0, 1.0);
            }
        `
        // 
        const fragment = `
            #ifdef GL_ES
            precision highp float;
            #endif

            uniform float uTime;
            varying vec2 vUv;

            vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
            vec2 mod289(vec2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
            vec3 permute(vec3 x) { return mod289(((x*34.0)+1.0)*x); }

            //
            // Description : GLSL 2D simplex noise function
            //      Author : Ian McEwan, Ashima Arts
            //  Maintainer : ijm
            //     Lastmod : 20110822 (ijm)
            //     License :
            //  Copyright (C) 2011 Ashima Arts. All rights reserved.
            //  Distributed under the MIT License. See LICENSE file.
            //  https://github.com/ashima/webgl-noise
            //
            float noise(vec2 v) {
                // Precompute values for skewed triangular grid
                const vec4 C = vec4(0.211324865405187,
                                    // (3.0-sqrt(3.0))/6.0
                                    0.366025403784439,
                                    // 0.5*(sqrt(3.0)-1.0)
                                    -0.577350269189626,
                                    // -1.0 + 2.0 * C.x
                                    0.024390243902439);
                                    // 1.0 / 41.0

                // First corner (x0)
                vec2 i  = floor(v + dot(v, C.yy));
                vec2 x0 = v - i + dot(i, C.xx);

                // Other two corners (x1, x2)
                vec2 i1 = vec2(0.0);
                i1 = (x0.x > x0.y)? vec2(1.0, 0.0):vec2(0.0, 1.0);
                vec2 x1 = x0.xy + C.xx - i1;
                vec2 x2 = x0.xy + C.zz;

                // Do some permutations to avoid
                // truncation effects in permutation
                i = mod289(i);
                vec3 p = permute(
                        permute( i.y + vec3(0.0, i1.y, 1.0))
                            + i.x + vec3(0.0, i1.x, 1.0 ));

                vec3 m = max(0.5 - vec3(
                                    dot(x0,x0),
                                    dot(x1,x1),
                                    dot(x2,x2)
                                    ), 0.0);

                m = m*m ;
                m = m*m ;

                // Gradients:
                //  41 pts uniformly over a line, mapped onto a diamond
                //  The ring size 17*17 = 289 is close to a multiple
                //      of 41 (41*7 = 287)
                vec3 x = 2.0 * fract(p * C.www) - 1.0;
                vec3 h = abs(x) - 0.5;
                vec3 ox = floor(x + 0.5);
                vec3 a0 = x - ox;

                // Normalise gradients implicitly by scaling m
                // Approximation of: m *= inversesqrt(a0*a0 + h*h);
                m *= 1.79284291400159 - 0.85373472095314 * (a0*a0+h*h);

                // Compute final noise value at P
                vec3 g = vec3(0.0);
                g.x  = a0.x  * x0.x  + h.x  * x0.y;
                g.yz = a0.yz * vec2(x1.x,x2.x) + h.yz * vec2(x1.y,x2.y);
                return 130.0 * dot(m, g);
            }

            void main() {
                vec2 st = vUv * 20.0;
                gl_FragColor.rgb = vec3(0.5 * noise(st) + 0.5);
                gl_FragColor.a = 1.0;
            }
        `

        const program = renderer.compileSync(fragment,vertex)
        renderer.useProgram(program)
        // 3.
        renderer.uniforms.uTime = 0.0
        // 4.
        renderer.setMeshData([
            {
                positions:[
                    [-1,-1],
                    [-1,1],
                    [1,1],
                    [1,-1],
                ],
                attributes:{
                    uv:[
                        [0,0],
                        [0,1],
                        [1,1],
                        [1,0],
                    ]
                },
                cells:[[0,1,2],[2,0,3]]
            }
        ])
        // 5.
        renderer.render()

        function update(uTime){
            renderer.uniforms.uTime = uTime
            requestAnimationFrame(update)
        }

        update(0.0)

    </script>
</body>
</html>